package owg.util.editor2d.modes;

import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;

import owg.util.Calc;
import owg.util.editor2d.Editor2D;
import owg.util.editor2d.entity.Placeable2D;
import owg.util.editor2d.entity.Rotateable2D;
import owg.util.editor2d.operations.Transformation.TransformationData;
import owg.util.euclidian.V2D;
import owg.util.opengl.EGL;

public class Rotate extends TransformationMode {
	public static float SLOW_MULTIPLIER = 0.1f;

	boolean individualOrigins;
	float radians;
	V2D firstOffset, pivotPos;
	
	public Rotate(Editor2D e, boolean individualOrigins) {
		super(e, "Rotate...");
		this.individualOrigins = individualOrigins;
		radians = 0;
		pivotPos = e.getPivotPos();
		firstOffset = e.eventHandler().getMousePosition().sub(pivotPos);
	}

	@Override
	protected boolean numberInputAllowed()
	{
		return true;
	}

	@Override
	protected void numberInputChanged(KeyEvent e)
	{
		update(e==null?false:e.isShiftDown());
	}

	private void update(boolean slow)
	{
		if(numberValue == null)
		{
			V2D currentOffset = editor.eventHandler().getMousePosition().sub(pivotPos);
			if(currentOffset.isZero() || firstOffset.isZero())
				radians = 0;
			else
				radians = (float) (currentOffset.angle(firstOffset)*Math.signum(currentOffset.dot(firstOffset.clone().perpendicular())))*(slow?SLOW_MULTIPLIER:1);
		}
		else
			radians = (float) (numberValue*Calc.toRad);

		V2D baseX = new V2D(Math.cos(radians), -Math.sin(radians));
		V2D baseY = baseX.clone().perpendicular().reverse();
		
		for (int i = 0; i < affectedIndices.length; i++)
		{
			TransformationData oldData = inverse.getData(i);
			int index = affectedIndices[i];
			Placeable2D p = editor.worldObjectsImmutable.get(index).a;
			if(p instanceof Rotateable2D)
			{
				Float oldAngle = oldData.angle;
				if(oldAngle == null)
					oldAngle = 0.0f;
				((Rotateable2D) p).setAngle(oldAngle+radians, true);
			}
			
			if(individualOrigins)
				p.setLocation(oldData.x, oldData.y, true);
			else
			{
				V2D origOffset = new V2D(oldData.x, oldData.y).sub(pivotPos);
				V2D newLoc = baseX.clone().multiply(origOffset.x()).add(baseY, origOffset.y());
				newLoc.add(pivotPos);
				editor.eventHandler().correctToGrid(newLoc, false);	
				p.setLocation(newLoc.x(), newLoc.y(), true);
			}
		}
		
		editor.editorUI().replaceMessage("Rotate "+numericalValueString(radians)+" degrees"+(individualOrigins?"(Rotation Only)":""));
	}

	@Override
	protected void key2(KeyEvent e)
	{
		if(e.getID() == KeyEvent.KEY_PRESSED)
		{
			if(e.getKeyCode() == KeyEvent.VK_R)
			{
				individualOrigins = !individualOrigins;
				update(e.isShiftDown());
				editor.modeListeners.fireEvents(e.getModifiers());
			}
			if(e.getKeyCode() == KeyEvent.VK_ENTER)
				terminate(false);
			else if(e.getKeyCode() == KeyEvent.VK_ESCAPE)
				terminate(true);
		}
	}
	public boolean individualOrigins()
	{
		return individualOrigins;
	}

	@Override
	protected String getMessage()
	{
		return "Rotated "+numericalValueString(radians)+" degrees"+(individualOrigins?"(Rotation Only)":"");
	}

	@Override
	public void render(EGL<?> egl) {}

	@Override
	public void mouse(MouseEvent e)
	{
		if((e.getID() == MouseEvent.MOUSE_MOVED || e.getID() == MouseEvent.MOUSE_DRAGGED) && numberValue == null)
			update(e.isShiftDown());
		else if(e.getID() == MouseEvent.MOUSE_RELEASED)
		{
			if(e.getButton() == MouseEvent.BUTTON1)
				terminate(false);
			else if(e.getButton() == MouseEvent.BUTTON3)
				terminate(true);
		}
	}
	
}
